<script setup>
import { getASK, postTest } from "@/api/user";
import testData from "../test.json";
import myTable from "./table.vue";
import myCharts from "./charts.vue";
import myMap from "./map.vue";

import MarkdownIt from "markdown-it";
import markdownItHighlightjs from "markdown-it-highlightjs";
import markdownItAnchor from "markdown-it-anchor";
import { showNotify } from "vant";

const props = defineProps({
  msg: String,
  // 默认消息
  messageObj: {
    type: Object,
    default: () => ({
      text: `你好！我是智能环保小助手，有什么可以帮你的？`,
      content: "你好！我是智能环保小助手，有什么可以帮你的？",
      isUser: false,
      type: 1,
      timestamp: Date.now(),
      loading: false, // 新增加载状态
      disabled: false, // 新增禁用状态
      tableData: [],
      labelData: []
      // chartData: testData
    })
  },
  // 是否显示 时间
  isTime: {
    type: Boolean,
    default: true
  },
  apiType: {
    type: String,
    default: "聊天"
  }
});

const emit = defineEmits([
  "update:message",
  "update:disabled",
  "scrollToBottom"
]);

// 初始化 Markdown 解析器
const md = new MarkdownIt().use(markdownItHighlightjs).use(markdownItAnchor);

const messages = ref([]);

watch(
  () => props.messageObj,
  newVal => {
    if (Object.keys(newVal).length > 0) {
      messages.value.push(newVal);
      emit("update:message", messages.value);
    }
  },
  { immediate: true, deep: true }
);

const sendMessage = async () => {
  if (!props.msg.trim()) return;

  // 用户消息（只添加一次）
  const userMsg = {
    text: props.msg,
    isUser: true,
    timestamp: Date.now()
  };

  // 全局加载消息（只添加一次）
  const aiLoadingMsg = {
    text: "",
    isUser: false,
    timestamp: Date.now(),
    loading: true,
    disabled: true
  };

  if (props.apiType === "聊天") {
    messages.value.push(userMsg, aiLoadingMsg);
  } else {
    messages.value = [aiLoadingMsg];
  }

  scrollToBottom();

  emit("update:message", messages.value);

  const loadingIndex = messages.value.length - 1;

  try {
    const formData = new FormData();
    formData.append("command", userMsg.text);
    const data =
      props.apiType === "聊天"
        ? await getASK({ question: userMsg.text })
        : await postTest(formData);

    if (data.code === 200) {
      // 先移除全局加载消息
      let answerList = [];
      messages.value.splice(loadingIndex, 1);
      if (data.data.answerList === undefined) {
        answerList = [data.data];
      } else {
        answerList = data.data.answerList;
      }

      // 顺序处理每个回答项
      for (const item of answerList) {
        // 为每个回答创建独立的加载消息
        const aiMsg = {
          text: "",
          isUser: false,
          timestamp: Date.now(),
          loading: true,
          disabled: true
        };

        messages.value.push(aiMsg);
        const msgIndex = messages.value.length - 1;
        scrollToBottom();

        // 处理表格数据
        let tableData = [];
        let labelData = [];
        if ([3, "3"].includes(item.answer.type)) {
          tableData = item.answer?.table?.rows;
          labelData = item.answer?.table?.columns;
        }

        // 处理图表数据
        const chartData = [4, "4"].includes(item.answer.type)
          ? {
              chartType: item.answer.echarts_type,
              options: {
                ...item.answer.option,
                series: item.answer.option?.series || []
              }
            }
          : null;

        // 构造消息内容
        const content = getMessageContent(item, tableData, chartData);

        // 更新消息
        messages.value[msgIndex] = {
          ...messages.value[msgIndex],
          ...item.answer,
          loading: false,
          disabled: true,
          text: "",
          content,
          labelData,
          tableData,
          chartData,
          value: [2, "2"].includes(item.answer.type)
            ? item.answer.value
            : undefined
        };

        // 启动逐字显示并等待完成
        await startTypewriterAnimation(msgIndex, content);

        // 等待100ms显示下一条（可选）
        await new Promise(resolve => setTimeout(resolve, 100));
      }
    } else if (data.code == 401) {
      messages.value.splice(loadingIndex, 1);
      return showNotify({
        type: "danger",
        message: "登录状态失效，请重新登录"
      });
    } else {
      addErrorMessage(data.msg);
    }
  } catch (error) {
    console.error("请求异常:", error);
    addErrorMessage(error.msg);
  }
};

// 重构数据
const refactoringData = async responseData => {
  try {
    // 数据标准化处理
    const normalizeData = data => {
      if (data?.data?.answerList) return data.data.answerList;
      if (data?.data) return [data.data];
      return [data];
    };

    const answerList = normalizeData(responseData);

    // 顺序处理每个回答项
    for (const item of answerList) {
      if (!item?.answer) {
        console.warn("无效数据格式，缺少 answer 字段", item);
        continue;
      }

      // 创建加载消息
      const aiMsg = {
        text: "",
        isUser: false,
        timestamp: Date.now(),
        loading: true,
        disabled: true
      };

      // 保留历史消息
      messages.value = [aiMsg];
      const msgIndex = messages.value.length - 1;
      scrollToBottom();

      // 表格数据处理
      let tableData = [];
      let labelData = [];
      if ([3, "3"].includes(item.answer.type)) {
        tableData = item.answer.table?.rows || [];
        labelData = item.answer.table?.columns || [];
      }

      // 图表数据处理
      const chartData = [4, "4"].includes(item.answer.type)
        ? {
            chartType: item.answer.echarts_type,
            options: {
              ...item.answer.option,
              series: item.answer.option?.series || []
            }
          }
        : null;

      // 内容验证生成
      const content = (() => {
        if ([3, "3"].includes(item.answer.type) && !tableData.length) {
          return "未查询到相关表格信息";
        }
        if (
          [4, "4"].includes(item.answer.type) &&
          !chartData?.options?.series?.length
        ) {
          return "未查询到相关图表信息";
        }
        return item.answer.text || "暂无相关信息";
      })();

      // 更新消息
      messages.value[msgIndex] = {
        ...messages.value[msgIndex],
        ...item.answer,
        loading: false,
        disabled: false, // 完成后启用交互
        text: "",
        content,
        labelData,
        tableData,
        chartData,
        // 保留原特殊字段处理
        value: [2, "2"].includes(item.answer.type)
          ? item.answer.value
          : undefined
      };

      // 执行动画
      await startTypewriterAnimation(msgIndex, content);

      // 消息间隔（根据需求调整）
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  } catch (error) {
    console.error("数据处理异常:", error);
    addErrorMessage("数据处理失败，请检查数据格式");
  }
};

// 辅助方法：获取消息内容
const getMessageContent = (item, tableData, chartData) => {
  if ([3, "3"].includes(item.answer.type) && !tableData.length) {
    return "未查询到相关表格信息";
  }
  if (
    [4, "4"].includes(item.answer.type) &&
    !chartData?.options?.series?.length
  ) {
    return "未查询到相关图表信息";
  }
  return item.answer.text || "暂无相关信息";
};

// 辅助方法：添加错误消息
const addErrorMessage = msg => {
  const loadingIndex = messages.value.length - 1;
  messages.value.splice(loadingIndex, 1);
  messages.value.push({
    text: msg || "请求失败，请重试",
    isUser: false,
    timestamp: Date.now(),
    loading: false,
    disabled: false
  });
  scrollToBottom();
};

// 改进的逐字显示动画（支持异步）
const startTypewriterAnimation = (index, fullText) => {
  return new Promise(resolve => {
    let currentIndex = 0;
    const typeInterval = setInterval(() => {
      if (currentIndex >= fullText.length) {
        clearInterval(typeInterval);
        messages.value[index].content = messages.value[index].text;
        messages.value[index].disabled = false;
        resolve();
        emit("update:message", messages.value);
        return;
      }
      messages.value[index].text = md.render(
        fullText.slice(0, currentIndex + 1)
      );
      currentIndex++;
      scrollToBottom();
    }, 50);
  });
};

/* 滚动到底部功能 */
const scrollToBottom = () => {
  nextTick(() => {
    // 等待DOM更新
    const contentDiv = document.querySelector(".content");
    if (contentDiv) {
      contentDiv.scrollTop = contentDiv.scrollHeight; // 设置滚动位置
    }
    emit("scrollToBottom");
  });
};

/* 时间格式化工具 */
const formatTime = timestamp => {
  const date = new Date(timestamp);
  // 补零处理并返回 HH:mm 格式
  return `${date.getHours().toString().padStart(2, "0")}:${date
    .getMinutes()
    .toString()
    .padStart(2, "0")}`;
};

/* 判断是否显示时间戳 */
const shouldShowTime = index => {
  if (index === 0) return true; // 第一条消息始终显示时间
  // 当前消息与上条消息间隔超过5分钟显示时间
  return (
    messages.value[index].timestamp - messages.value[index - 1].timestamp >
    300000
  );
};

defineExpose({
  sendMessage,
  refactoringData
});
</script>

<template>
  <!-- 消息展示区域 -->
  <div class="content" ref="content">
    <!-- 消息循环渲染 -->
    <div
      v-for="(msg, index) in messages"
      :key="index"
      :class="['message-container', msg.isUser ? 'user' : 'bot']"
    >
      <!-- 时间戳显示 -->
      <div v-if="shouldShowTime(index) && props.isTime" class="timestamp">
        {{ formatTime(msg.timestamp) }}
      </div>

      <!-- 消息包装容器 -->
      <div class="message-wrapper">
        <!-- 左侧消息结构（AI消息） -->
        <div class="left-content" v-if="!msg.isUser">
          <!-- 预留头像容器（v-if控制显隐） -->
          <div class="avatar-container" v-if="false">
            <div class="avatar"></div>
          </div>
          <!-- 消息内容 -->
          <div class="message-content">
            <div class="username" v-if="false">AI助手</div>
            <!-- 预留用户名 -->
            <div class="bubble" :class="{ loading: msg.loading }">
              <div v-html="msg.text" class="markdown"></div>

              <div
                v-if="
                  msg.text === msg.content && msg.text !== '未查询到相关信息'
                "
              >
                <div v-if="msg.type === 2 && !msg.text.includes(msg.value)">
                  {{ msg.value ?? "未查询到相关信息" }}
                </div>
                <van-button
                  v-if="msg?.references?.length > 0"
                  class="btnStyle"
                  size="small"
                  @click="msg.show = true"
                  >引用
                  {{ msg?.references?.length }}
                  数据库表
                  <van-icon name="arrow" />
                </van-button>

                <!-- 表格 -->
                <div v-if="[3].includes(msg.type)">
                  <myTable
                    :tableData="msg.tableData"
                    :labelData="msg.labelData"
                    @loadComplete="scrollToBottom"
                  />
                </div>

                <!-- 图表 -->
                <div v-if="[4].includes(msg.type)">
                  <myCharts
                    :chartData="msg.chartData"
                    @loadComplete="scrollToBottom"
                  />
                </div>

                <!-- 地图 -->
                <div v-if="[5].includes(msg.type)">
                  <myMap
                    :mapPoints="msg.map_points"
                    @loadComplete="scrollToBottom"
                  />
                </div>
              </div>
            </div>
            <!-- 消息气泡 -->
          </div>
        </div>

        <!-- 右侧消息结构（用户消息） -->
        <div class="right-content" v-if="msg.isUser">
          <div class="message-content">
            <div class="bubble">{{ msg.text }}</div>
          </div>
          <!-- 预留头像容器 -->
          <div class="avatar-container" v-if="false">
            <div class="avatar"></div>
          </div>
        </div>
      </div>

      <van-action-sheet
        v-model:show="msg.show"
        :actions="
          msg?.references?.map(item => {
            return {
              name: item,
              disabled: true
            };
          })
        "
        cancel-text="取消"
        close-on-click-action
        @cancel="show = false"
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
/* 加载动画 */
.loading {
  &::after {
    content: "...";
    display: inline-block;
    width: 1em;
    animation: dotPulse 2s infinite;
  }
}

@keyframes dotPulse {
  0% {
    content: "."; /* 单个点 */
  }
  25% {
    content: ".."; /* 两个点 */
  }
  50% {
    content: "..."; /* 三个点 */
  }
  75% {
    content: ".."; /* 回到两个点 */
  }
  100% {
    content: "."; /* 回到单个点 */
  }
}

.timestamp {
  text-align: left;
  color: #333;
  margin-bottom: 10px;
}

/* 打字效果 */
.bubble {
  // white-space: pre-wrap;
  overflow-wrap: break-word;
}

/* 消息展示区域 */
.content {
  flex: 1;
  padding: 10px;
  background: #f8f8f8;
  overflow: hidden;
  overflow-y: auto; /* 允许垂直滚动 */

  /* 消息容器基础样式 */
  .message-container {
    margin: 12px 0;

    /* AI消息样式（左对齐） */
    &.bot {
      .left-content {
        display: flex;
        align-items: flex-start;
        max-width: 100%; /* 限制最大宽度 */

        .message-content {
          overflow-x: auto;

          .bubble {
            background: white;
            border-radius: 18px 18px 18px 4px; /* 左气泡圆角 */
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
          }
        }
      }
    }

    /* 用户消息样式（右对齐） */
    &.user {
      .right-content {
        display: flex;
        justify-content: flex-end;
        margin-left: auto; /* 右侧对齐关键属性 */

        .message-content {
          .bubble {
            background: #95ec69;
            border-radius: 18px 18px 4px 18px; /* 右气泡圆角 */
          }
        }
      }
    }

    /* 消息气泡通用样式 */
    .bubble {
      padding: 12px 16px;
      line-height: 1.4;
      color: #333;
      word-break: break-word; /* 长文本换行处理 */
    }
  }
}

.btnStyle {
  margin-top: 10px;
}

:deep(.van-action-sheet__content) {
  .van-action-sheet__name {
    color: #646566 !important;
  }
}
</style>
